package com.huilian.iotbox.admin.wap.service.impl;

import com.huilian.iotbox.admin.wap.dao.MemberStoreBalanceDao;
import com.huilian.iotbox.admin.wap.service.*;
import com.huilian.iotbox.data.common.ServerResponse;
import com.huilian.iotbox.data.dto.*;
import com.huilian.iotbox.data.enums.*;
import com.huilian.iotbox.data.exception.SysException;
import com.huilian.iotbox.data.po.MemberStoreBalance;
import com.huilian.iotbox.data.utils.DateTimeUtils;
import com.huilian.iotbox.data.vo.MemberStoreBalanceVo;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;

@Service
@Slf4j
public class MemberStoreBalanceServiceImpl implements MemberStoreBalanceService {
    /**
     * 最高失败次数
     */
    private final static int count = 10;
    @Resource
    private MemberStoreBalanceDao memberStoreBalanceDao;


    @Override
    public Integer findDayMemberNewNumByUserId(StatsUserDto statsUserDto) {
        return memberStoreBalanceDao.findDayMemberNewNumByUserId(statsUserDto);
    }

    @Override
    public Integer findMemberNewNumByStoreId(StatsStoreDto statsStoreDto) {
        return memberStoreBalanceDao.findMemberNewNumByStoreId(statsStoreDto);
    }

    @Override
    public Integer findDayMemberOldNumByUserId(StatsUserDto statsUserDto) {
        return memberStoreBalanceDao.findDayMemberOldNumByUserId(statsUserDto);
    }


    @Override
    public Integer findMemberOldNumByStoreId(StatsStoreDto statsStoreDto) {
        return memberStoreBalanceDao.findMemberOldNumByStoreId(statsStoreDto);
    }



    @Override
    public MemberStoreBalanceVo findByMemberIdAndMerchantStoreId(MemberStoreBalanceDto memberStoreBalanceDto) {
        return memberStoreBalanceDao.findByMemberIdAndMerchantStoreId(memberStoreBalanceDto);
    }

    /**
     * 扣除会员余额（乐观锁） <br/>
     * 需要参数： <br/>
     * memberId <br/>
     * merchantStoreId <br/>
     * userId <br/>
     * 和对应需要扣除的数额即可
     *
     * @param runCount
     * @param memberStoreBalanceDto
     * @return
     * @throws Exception
     */
    @Override
    public MemberStoreBalanceDto minusBalance(int runCount, MemberStoreBalanceDto memberStoreBalanceDto) throws Exception {
        long begin = System.currentTimeMillis();
        log.info("为memberId:" + memberStoreBalanceDto.getMemberId() + "在场地:" + memberStoreBalanceDto.getMerchantStoreId() + "减少余额线程" + Thread.currentThread().getName() + "第" + runCount + "次执行");
        log.info("参数为：" + memberStoreBalanceDto);
        MemberStoreBalanceVo memberStoreBalanceVo = memberStoreBalanceDao.findByMemberIdAndMerchantStoreId(memberStoreBalanceDto);
        if (ObjectUtils.isEmpty(memberStoreBalanceVo)) {
            log.info("为memberId:" + memberStoreBalanceDto.getMemberId() + "在场地:" + memberStoreBalanceDto.getMerchantStoreId() + "减少余额失败！memberStoreBalanceId为空");
            throw new Exception("会员余额不足");
        }
        memberStoreBalanceDto.setId(memberStoreBalanceVo.getId());
        memberStoreBalanceDto.setMoneyRechargeBalance(memberStoreBalanceVo.getMoneyRechargeBalance());
        memberStoreBalanceDto.setMoneyDonateBalance(memberStoreBalanceVo.getMoneyDonateBalance());
        memberStoreBalanceDto.setRechargeBalance(memberStoreBalanceVo.getRechargeBalance());
        memberStoreBalanceDto.setDonateBalance(memberStoreBalanceVo.getDonateBalance());
        memberStoreBalanceDto.setLottery(memberStoreBalanceVo.getLottery());
        memberStoreBalanceDto.setIntegral(memberStoreBalanceVo.getIntegral());

        MemberStoreBalanceDto updateMemberStoreBalanceDto = new MemberStoreBalanceDto();
        updateMemberStoreBalanceDto.setId(memberStoreBalanceDto.getId());
        updateMemberStoreBalanceDto.setMemberId(memberStoreBalanceDto.getMemberId());
        updateMemberStoreBalanceDto.setUserId(memberStoreBalanceDto.getUserId());
        updateMemberStoreBalanceDto.setMerchantStoreId(memberStoreBalanceDto.getMerchantStoreId());

        //游戏币
        if (!ObjectUtils.isEmpty(memberStoreBalanceDto.getMinusCoins())) {
            if (memberStoreBalanceDto.getMinusCoins() > (memberStoreBalanceVo.getRechargeBalance() + memberStoreBalanceVo.getDonateBalance())) {
                log.info("为memberId:" + memberStoreBalanceDto.getMemberId() + "在场地:" + memberStoreBalanceDto.getMerchantStoreId() + "减少余额失败！memberStoreBalanceId为" + memberStoreBalanceVo.getId());
                throw new Exception("游戏币余额不足");
            } else {
                int coinBalance;
                //先扣除赠送币
                coinBalance = memberStoreBalanceVo.getDonateBalance() - memberStoreBalanceDto.getMinusCoins();
                if (coinBalance >= 0) {
                    updateMemberStoreBalanceDto.setDonateBalance(coinBalance);
                    memberStoreBalanceDto.setDonateBalance(coinBalance);

                    memberStoreBalanceDto.setMinusRechargeBalance(0);
                    memberStoreBalanceDto.setMinusDonateBalance(memberStoreBalanceDto.getMinusCoins());
                } else {
                    updateMemberStoreBalanceDto.setDonateBalance(0);
                    memberStoreBalanceDto.setDonateBalance(0);
                    memberStoreBalanceDto.setMinusRechargeBalance(Math.abs(coinBalance));

                    coinBalance = memberStoreBalanceVo.getRechargeBalance() + coinBalance;
                    updateMemberStoreBalanceDto.setRechargeBalance(coinBalance);
                    memberStoreBalanceDto.setRechargeBalance(coinBalance);

                    memberStoreBalanceDto.setMinusDonateBalance(memberStoreBalanceVo.getDonateBalance());
                }
            }
        }

        //彩票
        if (!ObjectUtils.isEmpty(memberStoreBalanceDto.getMinusLottery())) {
            if (memberStoreBalanceDto.getMinusLottery() > memberStoreBalanceVo.getLottery()) {
                log.info("为memberId:" + memberStoreBalanceDto.getMemberId() + "在场地:" + memberStoreBalanceDto.getMerchantStoreId() + "减少余额失败！memberStoreBalanceId为" + memberStoreBalanceVo.getId());
                throw new Exception("彩票余额不足");
            } else {
                updateMemberStoreBalanceDto.setLottery(memberStoreBalanceVo.getLottery() - memberStoreBalanceDto.getMinusLottery());
                memberStoreBalanceDto.setLottery(memberStoreBalanceVo.getLottery() - memberStoreBalanceDto.getMinusLottery());
            }
        }

        //积分余额
        if (!ObjectUtils.isEmpty(memberStoreBalanceDto.getMinusIntegral())) {
            if (memberStoreBalanceDto.getMinusIntegral() > memberStoreBalanceVo.getIntegral()) {
                log.info("为memberId:" + memberStoreBalanceDto.getMemberId() + "在场地:" + memberStoreBalanceDto.getMerchantStoreId() + "减少余额失败！memberStoreBalanceId为" + memberStoreBalanceVo.getId());
                throw new Exception("积分余额不足");
            } else {
                updateMemberStoreBalanceDto.setIntegral(memberStoreBalanceVo.getIntegral() - memberStoreBalanceDto.getMinusIntegral());
                memberStoreBalanceDto.setIntegral(memberStoreBalanceVo.getIntegral() - memberStoreBalanceDto.getMinusIntegral());
            }
        }
        updateMemberStoreBalanceDto.setLatelyPay(new Date());
        updateMemberStoreBalanceDto.setVersionId(memberStoreBalanceVo.getVersionId());

        int i = memberStoreBalanceDao.updateBalance(updateMemberStoreBalanceDto);
        if (i > 0) {
            log.info("为memberId:" + memberStoreBalanceDto.getMemberId() + "在场地:" + memberStoreBalanceDto.getMerchantStoreId() + "减少余额业务耗时：" + (System.currentTimeMillis() - begin) + "ms");
            return memberStoreBalanceDto;
        } else {
            if (count >= runCount) {
                return this.minusBalance(++runCount, memberStoreBalanceDto);
            } else {
                log.info("为memberId:" + memberStoreBalanceDto.getMemberId() + "在场地:" + memberStoreBalanceDto.getMerchantStoreId() + "减少余额失败！memberStoreBalanceId为" + memberStoreBalanceDto.getId());
                throw new Exception("为memberId:" + memberStoreBalanceDto.getMemberId() + "在场地:" + memberStoreBalanceDto.getMerchantStoreId() + "减少余额失败！memberStoreBalanceId为" + memberStoreBalanceDto.getId());
            }
        }
    }

    /**
     * 增加会员余额（乐观锁）<br/>
     * 需要参数：<br/>
     * memberId <br/>
     * merchantStoreId  <br/>
     * userId   <br/>
     * 和对应需要增加的数额即可
     *
     * @param runCount
     * @param memberStoreBalanceDto
     * @return
     * @throws Exception
     */
    @Override
    public MemberStoreBalanceDto addBalance(int runCount, MemberStoreBalanceDto memberStoreBalanceDto) throws Exception {
        long begin = System.currentTimeMillis();
        log.info("为memberId:" + memberStoreBalanceDto.getMemberId() + "在场地:" + memberStoreBalanceDto.getMerchantStoreId() + "增加余额线程" + Thread.currentThread().getName() + "第" + runCount + "次执行");
        log.info("参数为：" + memberStoreBalanceDto);
        MemberStoreBalanceVo memberStoreBalanceVo = memberStoreBalanceDao.findByMemberIdAndMerchantStoreId(memberStoreBalanceDto);
        //memberStoreBalanceVo如果为空，创新的
        if (ObjectUtils.isEmpty(memberStoreBalanceVo)) {
            MemberStoreBalanceDto newBalance = new MemberStoreBalanceDto();
            newBalance.setMemberId(memberStoreBalanceDto.getMemberId());
            newBalance.setMerchantStoreId(memberStoreBalanceDto.getMerchantStoreId());
            newBalance.setRegisterDeviceNo(null);
            newBalance.setUserId(memberStoreBalanceDto.getUserId());
            newBalance.setRechargeBalance(0);
            newBalance.setDonateBalance(0);
            newBalance.setIntegral(0);
            newBalance.setLottery(0);
            newBalance.setMoneyRechargeBalance(BigDecimal.ZERO);
            newBalance.setMoneyDonateBalance(BigDecimal.ZERO);
            newBalance.setStatus(MemberStoreBalanceStatusEnum.NORMAL.getCode());
            memberStoreBalanceDao.add(newBalance);
            memberStoreBalanceVo = new MemberStoreBalanceVo();
            memberStoreBalanceVo.setId(newBalance.getId());
            memberStoreBalanceVo.setMoneyRechargeBalance(newBalance.getMoneyRechargeBalance());
            memberStoreBalanceVo.setMoneyDonateBalance(newBalance.getMoneyDonateBalance());
            memberStoreBalanceVo.setRechargeBalance(newBalance.getRechargeBalance());
            memberStoreBalanceVo.setDonateBalance(newBalance.getDonateBalance());
            memberStoreBalanceVo.setLottery(newBalance.getLottery());
            memberStoreBalanceVo.setIntegral(newBalance.getIntegral());
        }
        memberStoreBalanceDto.setId(memberStoreBalanceVo.getId());
        memberStoreBalanceDto.setMoneyRechargeBalance(memberStoreBalanceVo.getMoneyRechargeBalance());
        memberStoreBalanceDto.setMoneyDonateBalance(memberStoreBalanceVo.getMoneyDonateBalance());
        memberStoreBalanceDto.setRechargeBalance(memberStoreBalanceVo.getRechargeBalance());
        memberStoreBalanceDto.setDonateBalance(memberStoreBalanceVo.getDonateBalance());
        memberStoreBalanceDto.setLottery(memberStoreBalanceVo.getLottery());
        memberStoreBalanceDto.setIntegral(memberStoreBalanceVo.getIntegral());

        MemberStoreBalanceDto updateMemberStoreBalanceDto = new MemberStoreBalanceDto();
        updateMemberStoreBalanceDto.setId(memberStoreBalanceDto.getId());
        updateMemberStoreBalanceDto.setMemberId(memberStoreBalanceDto.getMemberId());
        updateMemberStoreBalanceDto.setUserId(memberStoreBalanceDto.getUserId());
        updateMemberStoreBalanceDto.setMerchantStoreId(memberStoreBalanceDto.getMerchantStoreId());

        //人民币充值余额
        if (!ObjectUtils.isEmpty(memberStoreBalanceDto.getAddMoneyRechargeBalance())) {
            updateMemberStoreBalanceDto.setMoneyRechargeBalance(memberStoreBalanceVo.getMoneyRechargeBalance().add(memberStoreBalanceDto.getAddMoneyRechargeBalance()));
            memberStoreBalanceDto.setMoneyRechargeBalance(updateMemberStoreBalanceDto.getMoneyRechargeBalance());
        }
        //人民币赠送余额
        if (!ObjectUtils.isEmpty(memberStoreBalanceDto.getAddMoneyDonateBalance())) {
            updateMemberStoreBalanceDto.setMoneyDonateBalance(memberStoreBalanceVo.getMoneyDonateBalance().add(memberStoreBalanceDto.getAddMoneyDonateBalance()));
            memberStoreBalanceDto.setMoneyDonateBalance(updateMemberStoreBalanceDto.getMoneyDonateBalance());
        }
        //充值游戏币余额
        if (!ObjectUtils.isEmpty(memberStoreBalanceDto.getAddRechargeBalance())) {
            updateMemberStoreBalanceDto.setRechargeBalance(memberStoreBalanceVo.getRechargeBalance() + memberStoreBalanceDto.getAddRechargeBalance());
            memberStoreBalanceDto.setRechargeBalance(updateMemberStoreBalanceDto.getRechargeBalance());
        }
        //赠送游戏币余额
        if (!ObjectUtils.isEmpty(memberStoreBalanceDto.getAddDonateBalance())) {
            updateMemberStoreBalanceDto.setDonateBalance(memberStoreBalanceVo.getDonateBalance() + memberStoreBalanceDto.getAddDonateBalance());
            memberStoreBalanceDto.setDonateBalance(updateMemberStoreBalanceDto.getDonateBalance());
        }
        //彩票余额
        if (!ObjectUtils.isEmpty(memberStoreBalanceDto.getAddLottery())) {
            updateMemberStoreBalanceDto.setLottery(memberStoreBalanceVo.getLottery() + memberStoreBalanceDto.getAddLottery());
            memberStoreBalanceDto.setLottery(updateMemberStoreBalanceDto.getLottery());
        }
        //积分余额
        if (!ObjectUtils.isEmpty(memberStoreBalanceDto.getAddIntegral())) {
            updateMemberStoreBalanceDto.setIntegral(memberStoreBalanceVo.getIntegral() + memberStoreBalanceDto.getAddIntegral());
            memberStoreBalanceDto.setIntegral(updateMemberStoreBalanceDto.getIntegral());
        }
        updateMemberStoreBalanceDto.setVersionId(memberStoreBalanceVo.getVersionId());

        int i = memberStoreBalanceDao.updateBalance(updateMemberStoreBalanceDto);
        if (i > 0) {
            log.info("为memberId:" + memberStoreBalanceDto.getMemberId() + "在场地:" + memberStoreBalanceDto.getMerchantStoreId() + "增加余额业务耗时：" + (System.currentTimeMillis() - begin) + "ms");
            return memberStoreBalanceDto;
        } else {
            if (count >= runCount) {
                return this.addBalance(++runCount, memberStoreBalanceDto);
            } else {
                log.info("为memberId:" + memberStoreBalanceDto.getMemberId() + "在场地:" + memberStoreBalanceDto.getMerchantStoreId() + "增加余额失败！memberStoreBalanceId为" + memberStoreBalanceDto.getId());
                throw new Exception("为memberId:" + memberStoreBalanceDto.getMemberId() + "在场地:" + memberStoreBalanceDto.getMerchantStoreId() + "增加余额失败！memberStoreBalanceId为" + memberStoreBalanceDto.getId());
            }
        }
    }


    @Getter
    public enum CoinTypeEnum {
        RECHARGE_COIN(1, "充值币"),
        GIFT_COIN(2, "赠送币"),
        INTEGRAL(3, "积分"),
        LOTTERY_TICKET(4, "彩票"),
        RECHARGE_BALANCE(5, "充值余额"),
        GIFT_BALANCE(6, "赠送余额");
        //枚举值所包含的属性
        private Integer id;
        private String desc;

        //构造方法
        CoinTypeEnum(Integer id, String desc) {
            this.id = id;
            this.desc = desc;
        }
    }
}
